package com.catazy.album.data.repository

import com.catazy.album.data.datasource.api.model.toDomainModel
import com.catazy.album.data.datasource.api.model.toEntityModel
import com.catazy.album.data.datasource.api.service.AlbumRetrofitService
import com.catazy.album.data.datasource.database.AlbumDao
import com.catazy.album.data.datasource.database.model.toDomainModel
import com.catazy.album.domain.model.Album
import com.catazy.album.domain.repository.AlbumRepository
import com.catazy.base.data.retrofit.ApiResult
import com.catazy.base.domain.result.Result
import timber.log.Timber

/**
 * 作者: Tao
 * 日期: 2024/12/23
 * 时间: 09:53
 * 描述: 现了AlbumRepository接口的类，用于处理与专辑相关的数据操作。
 * 它结合了来自网络API和本地数据库的数据，以提供全面的专辑信息。
 */
internal class AlbumRepositoryImpl(
    private val albumRetrofitService: AlbumRetrofitService,
    private val albumDao: AlbumDao,
) : AlbumRepository {

    /**
     * 根据用户输入的关键词搜索专辑信息。
     * 优先从API获取数据，如果API调用失败，则从本地数据库获取数据。
     *
     * @param phrase 用户输入的搜索关键词，可能为null。
     * @return 包含搜索结果的Result对象，如果搜索失败，返回空列表。
     */
    override suspend fun searchAlbum(phrase: String?): Result<List<Album>> =
        when (val apiResult = albumRetrofitService.searchAlbumAsync(phrase)) {

            is ApiResult.Success -> {
                // 处理API成功返回的数据，将其转换为领域模型并保存到本地数据库
                val albums = apiResult
                    .data
                    .results
                    .albumMatches
                    .album
                    .also { albumsApiModels ->
                        val albumEntityModels = albumsApiModels.map { it.toEntityModel() }
                        albumDao.insertAlbums(albumEntityModels)
                    }
                    .map { it.toDomainModel() }

                Result.Success(albums)
            }

            is ApiResult.Error -> {
                // 处理API错误情况，返回失败结果
                Result.Failure()
            }

            is ApiResult.Exception -> {
                // 处理API异常情况，记录日志并从本地数据库获取数据
                Timber.e(apiResult.throwable)
                val albums = albumDao.getAll().map { it.toDomainModel() }
                Result.Success(albums)
            }
        }

    /**
     * 获取特定专辑的详细信息。
     * 优先从API获取数据，如果API调用失败，则从本地数据库获取数据。
     *
     * @param artistName 专辑艺术家的名称。
     * @param albumName 专辑的名称。
     * @param mbId 专辑的MusicBrainz ID，可能为null。
     * @return 包含专辑详细信息的Result对象，如果获取失败，返回空对象。
     */
    override suspend fun getAlbumInfo(
        artistName: String,
        albumName: String,
        mbId: String?
    ): Result<Album> =
        when (val apiResult = albumRetrofitService.getAlbumInfoAsync(artistName, albumName, mbId)) {

            is ApiResult.Success -> {
                // 处理API成功返回的数据，将其转换为领域模型
                val album = apiResult
                    .data
                    .album
                    .toDomainModel()

                Result.Success(album)
            }

            is ApiResult.Error -> {
                // 处理API错误情况，返回失败结果
                Result.Failure()
            }

            is ApiResult.Exception -> {
                // 处理API异常情况，记录日志并从本地数据库获取数据
                Timber.e(apiResult.throwable)

                val album = albumDao
                    .getAlbum(artistName, albumName, mbId)
                    .toDomainModel()

                Result.Success(album)
            }
        }
}
